package org.cnc.explain.lifecycle;

import org.cnc.explain.lifecycle.beaninitial_8.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * <p>
 * #TODO: desc
 * </p>
 *
 * @author zhiyong.tan
 * @since 2022-08-31
 */
public class Step8BeanInitialize {

	@Test
	public void testInitMethod() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanInitConfiguration.class);
		BeanInitializeBean bean = context.getBean(BeanInitializeBean.class);
	}

	@Test
	public void testBeanAwareBeanCallbacks() {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInitConfiguration.class);
		ctx.register(BeanAwareBean.class);
		System.out.println("完成bean注入");
		BeanAwareBean bean = ctx.getBean(BeanAwareBean.class);
		System.out.println(bean);
	}

	@Test
	public void testPriorityAfterPropertiesSetAndInitMethod(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInitConfiguration.class);
		PriorityAfterPropertiesSetAndInitMethodBean bean = ctx.getBean(PriorityAfterPropertiesSetAndInitMethodBean.class);
		System.out.println(bean);
	}


	@Test
	public void testChangeBeanPropertiesByPostProcessAfterInitialization(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInitConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(
				new BeanPostProcessor() {
					@Override
					public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
						if("postProcessAfterInitializationBean".equals(beanName)){
							try {
								Method method = bean.getClass().getMethod("setName",String.class);
								method.invoke(bean,"from postProcessAfterInitializationBean");
							} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
								e.printStackTrace();
							}
						}
						return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
					}
				}
		);
		ctx.register(PostProcessAfterInitializationBean.class);
		PostProcessAfterInitializationBean bean = ctx.getBean(PostProcessAfterInitializationBean.class);
		System.out.println(bean);
	}

	@Test
	public void testReturnNewBeanByPostProcessAfterInitialization(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInitConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(
				new BeanPostProcessor() {
					@Override
					public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
						if("postProcessAfterInitializationBean".equals(beanName)){
							PostProcessAfterInitializationBean newBean=  new PostProcessAfterInitializationBean();
							newBean.setName("from new Bean");
							return newBean;
						}
						return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
					}
				}
		);
		ctx.register(PostProcessAfterInitializationBean.class);
		PostProcessAfterInitializationBean bean = ctx.getBean(PostProcessAfterInitializationBean.class);

		ctx.close();
		System.out.println(bean);
	}

}
